package com.ponhu.ea2.goodsCenter.bms.api.utils;

import com.alibaba.nacos.common.utils.StringUtils;
import com.ponhu.ea2.vo.PickExportVo;
import com.ponhu.ea2.vo.PickInventoryExportVo;
import com.ponhu.ea2.vo.PickInventoryImgExportVo;
import io.netty.util.concurrent.FastThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Wang
 * @date 2021/10/26 4:10 下午
 */
@Slf4j
@Component
public class CommonUtils {

    private static final RestTemplate restTemplate = new RestTemplate();

    static {
        restTemplate.setInterceptors(new ArrayList<>());
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                // maxConnTotal是同时间正在使用的最多的连接数
                .setMaxConnTotal(500)
                // maxConnPerRoute是针对一个域名同时间正在使用的最多的连接数
                .setMaxConnPerRoute(500)
                .build();
        HttpComponentsClientHttpRequestFactory httpRequestFactory =
                new HttpComponentsClientHttpRequestFactory(httpClient);
        // 高并发下等待链接超时
        httpRequestFactory.setConnectionRequestTimeout(60000);
        httpRequestFactory.setConnectTimeout(60000);
        // 成功建立链接后的读取超时
        httpRequestFactory.setReadTimeout(15000);
        restTemplate.setRequestFactory(httpRequestFactory);
    }

    @Autowired
    private FastThreadLocal<String> traceIdLocal;

    public static String getTraceId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 选品工具有图导出
     *
     * @param imageDataList
     * @return
     */
    public List<PickExportVo> getInputStreamParallel(List<PickExportVo> imageDataList) {
        String traceId = traceIdLocal.get();
        long start = System.currentTimeMillis();

        int limit = imageDataList.size();
        int nThreads = Math.min(100, limit);
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
        try {
            ConcurrentHashMap<String, InputStream> concurrentHashMap = new ConcurrentHashMap();

            CompletableFuture[] futureArr = new CompletableFuture[nThreads];
            for (int i = 0; i < nThreads; i++) {
                int finalI = i;
                int unitNum = (limit + nThreads - 1) / nThreads; // 单位数量（向上取整）
                CompletableFuture<List<PickInventoryExportVo>> listCompletableFuture = CompletableFuture
                        .supplyAsync(() -> imageDataList.stream().skip(finalI * unitNum).limit(unitNum).map(imageData -> {
                            PickInventoryImgExportVo exportVo = (PickInventoryImgExportVo) imageData;
                            InputStream inputStream = getInputStreamByUrl(traceId, exportVo.getMainImage(), 1);
                            try {
                                if (ObjectUtils.isNotEmpty(inputStream)) {
                                    concurrentHashMap.put(exportVo.getMainImage(), inputStream);
                                    exportVo.setInputStream(inputStream);
                                }
                            } finally {
                                if (ObjectUtils.isNotEmpty(inputStream)) {
                                    try {
                                        inputStream.close();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                            return exportVo;
                        }).collect(Collectors.toList()), executorService);
                futureArr[i] = listCompletableFuture;
            }
            CompletableFuture.allOf(futureArr).join();

//            System.out.printf("\033[32m ===>> CompletableFuture.allOf(futureArr).join() <<=== \033[0m\n");

            List<PickExportVo> pickInventoryExportVos = Arrays.asList(futureArr).parallelStream()
                    .flatMap(future -> ((List<PickInventoryImgExportVo>) future.join()).stream())
//                .filter(imageData -> ObjectUtils.isNotEmpty(imageData.getInputStream()))
                    .collect(Collectors.toList());

//            System.out.printf("\033[32m getInputStreamParallel ===>> %s ms \033[0m\n", System.currentTimeMillis() - start);

            return pickInventoryExportVos;
        } finally {
            if (!executorService.isShutdown()) executorService.shutdown();
        }
    }

    /**
     * 获取指定图片链接的输入流
     */
    public static InputStream getInputStreamByUrl(String traceId, String imgUrl, int retry) {
        try {
            if (StringUtils.isEmpty(imgUrl)) return null;
            Resource resource = restTemplate.getForObject(imgUrl + "?imageView2/2/w/200", Resource.class);
            return resource.getInputStream();
        } catch (Exception e) {
//            e.printStackTrace();
            if (retry >= 10) {
                log.error("getInputStreamByUrl 超时 ===>> [{}] ===>> retry={} ===>> {}", traceId, retry, imgUrl);
                return null;
            }
            return getInputStreamByUrl(traceId, imgUrl, ++retry);
        }
    }

}
